#pragma once
// 和网络 中 连接/连接池 有关的函数放这里

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>   //uintptr_t
#include <stdarg.h>   //va_start....
#include <unistd.h>   //STDERR_FILENO等
#include <sys/time.h> //gettimeofday
#include <time.h>     //localtime_r
#include <fcntl.h>    //open
#include <errno.h>    //errno
// #include <sys/socket.h>
#include <sys/ioctl.h> //ioctl
#include <arpa/inet.h>

#include "ngx_c_conf.h"
#include "ngx_macro.h"
#include "ngx_global.h"
#include "ngx_func.h"
#include "ngx_c_socket.h"

lpngx_connection_t CSocekt::ngx_get_connection(int isock)
{
    lpngx_connection_t c = m_pfree_connections; // 获取空闲连接链表头
    if (c == nullptr)
    {
        // 系统应该控制连接数量，防止空闲连接被耗尽，能走到这里，都不正常
        ngx_log_stderr(0, "CSocekt::ngx_get_connection()中空闲链表为空,这不应该!");
        return nullptr;
    }

    m_pfree_connections = c->data; // 空闲连接指针向后移动
    m_free_connection_n--;

    //(1)获取要用的变量
    uintptr_t instance = c->instance; // 常规c->instance在刚构造连接池时这里是1【失效】
    uint64_t iCurrsequence = c->iCurrsequence;

    //(2)赋值
    memset(c, 0, sizeof(ngx_connection_t));
    c->fd = isock;
    c->curStat = _PKG_HD_INIT; // 准备开始接收包头

    c->precvbuf = c->dataHeadInfo;         // 先指向存放包头的空间，准备接收包头
    c->irecvlen = sizeof(COMM_PKG_HEADER); // 这里指定收数据的长度，这里先要求收包头这么长字节的数据

    c->ifnewrecvMem = false;  // 标记我们并没有new内存，所以不用释放
    c->pnewMemPointer = NULL; // 既然没new内存，那自然指向的内存地址先给NULL
    // ...

    //(3)这个值有用，所以在上边(1)中被保留，没有被清空，这里又把这个值赋回来
    c->instance = !instance;
    c->iCurrsequence = iCurrsequence;
    ++c->iCurrsequence; // 每次取用该值都增加1

    // wev->write = 1;  这个标记有没有 意义加，后续再研究
    return c;
}

// 归还参数c所代表的连接到到连接池中，注意参数类型是lpngx_connection_t
void CSocekt::ngx_free_connection(lpngx_connection_t c)
{
    if (c->ifnewrecvMem == true)
    {
        // 我们曾经给这个连接分配过内存，则要释放内存
        CMemory::GetInstance()->FreeMemory(c->pnewMemPointer);
        c->pnewMemPointer = NULL;
        c->ifnewrecvMem = false; // 这行有用？
    }

    c->data = m_pfree_connections; // 回收的节点指向原来串起来的空闲链的链头

    // 节点本身也要干一些事
    ++c->iCurrsequence; // 回收后，该值就增加1,以用于判断某些网络事件是否过期【一被释放就立即+1也是有必要的】

    m_pfree_connections = c; // 修改 原来的链头使链头指向新节点
    ++m_free_connection_n;   // 空闲连接多1
    return;
}

void CSocekt::ngx_close_connection(lpngx_connection_t c)
{
    if (close(c->fd) == -1)
    {
        ngx_log_error_core(NGX_LOG_ALERT, errno, "CSocekt::ngx_close_connection()中close(%d)失败!", c->fd);
    }
    c->fd = -1;
    ngx_free_connection(c);
    return;
}
